package com.south.base.test.arithmetic;

import org.junit.Assert;
import org.junit.Test;

/**
 * @author Administrator
 * @date 2020/5/27 10:45
 */
public class NumberToWords {
    private final static String[] zeroToNineteen = {"Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen", "Sixteen", "Seventeen", "Eighteen", "Nineteen"};
    private final static String[] twentyToNinety = {"Twenty", "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"};
    private static final int BILLION = 1000000000;
    private static final int MILLION = 1000000;
    private static final int THOUSAND = 1000;
    private static final int HUNDRED = 100;
    private static final int[] SUFFIX = {HUNDRED, THOUSAND, MILLION, BILLION};
    private static final String[] SUFFIX_STR = {"Hundred", "Thousand", "Million", "Billion"};
    private static final String SEPARATOR = " ";

    @Test
    public void test() {
        Assert.assertEquals("One Hundred Twenty Three", numberToWords(123));
        Assert.assertEquals("Twelve Thousand Three Hundred Forty Five", numberToWords(12345));
        Assert.assertEquals("One Million Two Hundred Thirty Four Thousand Five Hundred Sixty Seven", numberToWords(1234567));
        Assert.assertEquals("One Billion Two Hundred Thirty Four Million Five Hundred Sixty Seven Thousand Eight Hundred Ninety One", numberToWords(1234567891));
    }

    /**
     * 整数转换英文表示
     * 将非负整数转换为其对应的英文表示。可以保证给定输入小于 231 - 1 。
     * @param num
     * @return
     */
    public String numberToWords(int num) {
        if (num == 0) {
            return "Zero";
        }
        StringBuilder builder = new StringBuilder();
        for (int i = SUFFIX.length - 1; i >= 0; i--) {
            if (num >= SUFFIX[i]) {
                if (builder.length() != 0) {
                    builder.append(SEPARATOR);
                }
                builder.append(numberToWords(num / SUFFIX[i])).append(SEPARATOR).append(SUFFIX_STR[i]);
                num %= SUFFIX[i];
            }
        }
        if (num < 20) {
            if (num != 0) {
                if (builder.length() != 0) {
                    builder.append(SEPARATOR);
                }
                builder.append(zeroToNineteen[num]);
            }
        } else {
            if (builder.length() != 0) {
                builder.append(SEPARATOR);
            }
            builder.append(twentyToNinety[num / 10 - 2]);
            if (num % 10 != 0) {
                if (builder.length() != 0) builder.append(SEPARATOR);
                builder.append(zeroToNineteen[num % 10]);
            }
        }
        return builder.toString();
    }
}
